<!--
 * @Description: 入院登记
 * @Author: 梁青春
 * @Date: 2025-10-11 09:30:17
 * @LastEditTime: 2025-11-20 14:35:05
 * @LastEditors: 梁青春
-->
<template>
  <navbar />
  <container>
    <!-- 左侧：患者搜索和列表 -->
    <template #left>
      <div class="left-panel">
        <div class="search-add left-heard">
          <div class="search-box">
            <el-input
              v-model="searchText"
              placeholder="请输入患者姓名"
              clearable
              @keyup.enter="loadAdmissionList"
              @input="loadAdmissionList"
            ></el-input>
          </div>
          <div class="add-box">
            <el-button type="primary" @click="addPatient" :icon="Plus">登记</el-button>
          </div>
        </div>
        <div class="todo-date">
          <div class="tabs">
            <h-tabs :tabs="[{ label: '住院办理', value: 1, badge: 3, offset: [5, 2] }]" v-model="activeTab" />
          </div>
          <div class="date-picker">
            <el-button class="date-picker-val" @click="handleToggleDatePicker">
              {{ formatDateValue(dateValue) }} <el-icon><CaretBottom /></el-icon>
            </el-button>
            <div v-if="showDatePicker" class="date-picker-panel" ref="datePickerPanelRef">
              <el-date-picker
                v-model="dateValue"
                type="date"
                placeholder="选择日期"
                format="MM-DD"
                value-format="YYYY-MM-DD"
                @change="handleDateChange"
                :teleported="false"
                style="width: 100%"
              />
            </div>
          </div>
        </div>
        <div class="patient-list">
          <div class="patient-item" v-for="item in patientList" :key="item.id" @click="handleClickPatient(item)">
            <div class="patient-icon iconfont" :class="[item.gender === '2' ? 'icon-woman' : 'icon-man']"></div>
            <div class="patient-info">
              {{ item.name }} {{ item.age?.split('岁')[0] > 0 ? item.age?.split('岁')[0] + '岁' : item.age }}
              {{ parseTime(item.admissionTime, '{h}:{m}') }}
            </div>
            <div class="patient-status">
              {{ item.processState === '1' ? '已办理' : '待办理' }}
            </div>
          </div>
        </div>
      </div>
      <RegisterAdmissionDialog v-model="dialogVisible" @submitted="loadAdmissionList" />
    </template>

    <!-- 中间：患者详细信息 -->
    <template #default>
      <div v-if="isPatientEmpty" class="empty-container container-body">
        <el-empty :image-size="120" description="暂无患者信息">
          <div class="empty-hint">请从左侧选择患者查看详细信息</div>
        </el-empty>
      </div>
      <div v-else class="patient-main container-body">
        <div class="patient-title">
          <div class="patient-info">
            {{ patientInfo?.name || '未选择患者' }}
            {{ patientInfo?.gender === '2' ? '女' : '男' }}
            {{ patientInfo?.age?.split('岁')[0] > 0 ? patientInfo?.age?.split('岁')[0] + '岁' : patientInfo?.age }}
          </div>
          <div class="title-opt">
            <el-button type="primary" v-if="!isEditing" @click="isEditing = true">修改</el-button>
            <el-button type="success" v-if="isEditing" @click="handleUpdateSubmit">保存</el-button>
            <el-button v-if="isEditing" @click="isEditing = false">取消</el-button>
            <el-button type="primary" v-if="hospitalInfo.processState !== '1'" @click="openAdmissionDialog"
              >办理住院</el-button
            >
            <el-button v-if="hospitalInfo.processState === '1'">退院</el-button>
            <el-button type="primary" v-if="hospitalInfo.processState === '1'" @click="openDepositDialog"
              >缴押金</el-button
            >
            <el-button v-if="hospitalInfo.processState === '1'">打印</el-button>
          </div>
        </div>
        <div class="patient-content">
          <div class="patient-content">
            <div class="patient-item">
              <div class="title">患者信息</div>
              <PatientInfo :edit="!isEditing" :patient="patientInfo" ref="mainPatientInfoRef" />
            </div>
            <div class="patient-item">
              <div class="title">
                住院信息
                <div class="sub-title">
                  入院:{{ new Date().getFullYear() }}年第{{ hospitalInfo?.currentYearCount || 1 }}次/累计第{{
                    hospitalInfo?.totalCount || 1
                  }}次
                </div>
              </div>
              <HospitalizationInfo
                :edit="!isEditing"
                :patient="hospitalInfo"
                :isShowDeposit="true"
                ref="mainHospitalizationInfoRef"
              />
            </div>
          </div>
        </div>
      </div>

      <!-- 入院办理弹窗组件：通过 v-model 控制显隐，并传入初始数据 -->
      <AdmissionHandleDialog
        v-model="admissionDialogVisible"
        :initial-data="admissionInitData"
        @submit="handleAdmissionSubmit"
      />
      <DepositPayDialog
        v-model="depositDialogVisible"
        :initial-amount="depositInitAmount"
        :admission="depositAdmission"
        @submit="handleDepositSubmit"
      />
    </template>

    <!-- 右侧：操作按钮和历史记录 -->
    <template #right>
      <div v-if="isPatientEmpty" class="empty-container">
        <el-empty :image-size="80" description="未选择患者" />
      </div>
      <div v-else class="right-panel">
        <el-tabs v-model="activeName" class="demo-tabs" @tab-change="changeTab">
          <el-tab-pane :label="`历史（${total}）`" name="his">
            <div class="his-content">
              <div v-for="item in rightHistoryList" :key="item.id" class="his-content-item his-info">
                <div class="his-info-title">
                  <span>{{ item.patientName }}</span>
                  <span>{{ item.name }}</span>
                </div>
                <div class="his-info-content">
                  <span>{{ item.content }}</span>
                </div>
                <div class="his-info-time">
                  <span>{{ item.user }}</span
                  ><span>{{ item.time }}</span>
                </div>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane :label="`押金缴费历史（${payList.length}）`" name="hisPay">
            <div class="his-content">
              <div v-for="item in payList" :key="item.id" class="his-content-item his-info">
                <div class="his-info-title">
                  <span>{{
                    item.payType === 'cash'
                      ? '现金'
                      : item.payType === 'card'
                        ? '银行卡'
                        : item.payType === 'wechat'
                          ? '微信'
                          : item.payType === 'alipay'
                            ? '支付宝'
                            : '未知'
                  }}</span>
                  <span>{{ item.deposit }}</span>
                </div>
                <div class="his-info-time">
                  <span>{{ item.createTime }}</span>
                </div>
              </div>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>
    </template>
  </container>
</template>

<script setup name="AdmissionRegistration">
import { ref, reactive, toRefs, computed, watch, onMounted, onUnmounted, getCurrentInstance } from 'vue'
import PatientInfo from './components/PatientInfo.vue'
import HospitalizationInfo from './components/HospitalizationInfo.vue'
import RegisterAdmissionDialog from './components/RegisterAdmissionDialog.vue'
import AdmissionHandleDialog from './components/AdmissionHandleDialog.vue'
import DepositPayDialog from './components/DepositPayDialog.vue'
import {
  getAdmissionList,
  registerAdmission,
  getAdmissionRegInfoByHospitalizationNo,
  updateAdmission,
  loadPaymentList,
  handleAdmission
} from '@/api/chargingWork/admissionRegistration'

// 常量
const DEFAULT_DATE_RANGE_DAYS = 3
const DEFAULT_DEPOSIT_AMOUNT = 0

// 基础实例
const { proxy } = getCurrentInstance()

// 数据定义
const state = reactive({
  patientSelect: {},
  activeTab: 1,
  dateValue: null,
  showDatePicker: false,
  dialogVisible: false,
  searchText: ''
})
const { patientSelect, activeTab, dateValue, showDatePicker, dialogVisible, searchText } = toRefs(state)
const datePickerPanelRef = ref(null)
const patientList = ref([])
const depositDialogVisible = ref(false)
const depositInitAmount = ref(DEFAULT_DEPOSIT_AMOUNT)
const depositAdmission = ref({})
const hospitalInfo = ref({})
const patientInfo = ref({})
const mainPatientInfoRef = ref(null)
const mainHospitalizationInfoRef = ref(null)
const isEditing = ref(false)
const hospitalizationNumber = ref('')
const activeName = ref('his')
const total = ref(3)
const rightHistoryList = ref([
  { id: 1, patientName: '出院', name: '住院15天', content: '', user: '管理员', time: '2025-10-14 20:02:35' },
  {
    id: 2,
    patientName: '更新',
    name: '',
    content: '添加紧急联系人张敏(夫妻) 18931125555;联系电话由18931128888变更为18931126666；',
    user: '管理员',
    time: '2025-10-14 20:02:35'
  },
  {
    id: 3,
    patientName: '入院（第1次）  ',
    name: '支原体性肺炎',
    content: '',
    user: '管理员',
    time: '2025-10-14 20:02:35'
  }
])
const payList = ref([])

// 计算属性
const isPatientEmpty = computed(() => {
  const p = patientSelect.value || {}
  return !p.admissionId
})

// 方法：患者选择与列表
const handleChangePatient = val => {
  patientSelect.value = val
}
const handleClickPatient = item => {
  handleChangePatient(item)
}
const loadAdmissionList = async () => {
  const params = { name: searchText.value }
  if (dateValue.value) {
    params.admissionTime = dateValue.value
  } else {
    params.startTime = proxy.parseTime(new Date() - DEFAULT_DATE_RANGE_DAYS * 24 * 60 * 60 * 1000, '{y}-{m}-{d}')
    params.endTime = proxy.parseTime(new Date(), '{y}-{m}-{d}')
  }
  const res = await getAdmissionList(params)
  if (res.code === 200) patientList.value = res.data || []
}
const addPatient = () => {
  dialogVisible.value = true
}

// 方法：日期选择器
const handleToggleDatePicker = () => {
  showDatePicker.value = !showDatePicker.value
}
const formatDateValue = value => {
  if (!value) return '近三天'
  return value
}
const handleDateChange = value => {
  dateValue.value = value
  showDatePicker.value = false
  loadAdmissionList()
}
const handleDocumentClick = event => {
  const datePickerContainer = event.target.closest('.date-picker')
  if (!datePickerContainer && showDatePicker.value) showDatePicker.value = false
}

// 方法：入院与信息维护
const getPatientInfo = async admission => {
  if (!admission || !admission.hospitalizationNumber) return
  const no = admission.izationNumber
  const res = await getAdmissionRegInfoByHospitalizationNo(no)
  if (res.code === 200) {
    hospitalInfo.value = res.data || {}
    patientInfo.value = res.data?.patientInfo || {}
  }
}
const handleUpdateSubmit = async () => {
  const info = await mainPatientInfoRef.value.exposeForm()
  if (!info) return
  const hosp = await mainHospitalizationInfoRef.value.exposeForm()
  if (!hosp) return
  if (info.birthPlace && info.birthPlace.length >= 3) {
    info.birthProvince = info.birthPlace[0] ?? ''
    info.birthCity = info.birthPlace[1] ?? ''
    info.birthDistrict = info.birthPlace[2] ?? ''
  }
  if (info.nativePlace && info.nativePlace.length >= 3) {
    info.nativeProvince = info.nativePlace[0] ?? ''
    info.nativeCity = info.nativePlace[1] ?? ''
    info.nativeDistrict = info.nativePlace[2] ?? ''
  }
  if (info.accountAddress && info.accountAddress.length >= 3) {
    info.householdProvince = info.accountAddress[0] ?? ''
    info.householdCity = info.accountAddress[1] ?? ''
    info.householdDistrict = info.accountAddress[2] ?? ''
  }
  if (info.homeAddress && info.homeAddress.length >= 3) {
    info.homeProvince = info.homeAddress[0] ?? ''
    info.homeCity = info.homeAddress[1] ?? ''
    info.homeDistrict = info.homeAddress[2] ?? ''
  }
  if (info.companyAddress && info.companyAddress.length >= 3) {
    info.companyProvince = info.companyAddress[0] ?? ''
    info.companyCity = info.companyAddress[1] ?? ''
    info.companyDistrict = info.companyAddress[2] ?? ''
  }
  if (info.contactAddress && info.contactAddress.length >= 3) {
    info.contactProvince = info.contactAddress[0] ?? ''
    info.contactCity = info.contactAddress[1] ?? ''
    info.contactDistrict = info.contactAddress[2] ?? ''
  }
  const form = { patient: info, admission: hosp }
  await updateAdmission(form)
  isEditing.value = false
}

// 方法：入院办理与押金支付
const admissionDialogVisible = ref(false)
const admissionInitData = ref({ patientName: '', deptName: '', wardName: '', admissionAt: new Date(), deposit: 0 })
const openAdmissionDialog = () => {
  const p = hospitalInfo.value || {}
  admissionInitData.value = {
    patientName: p?.patientInfo?.name ?? '',
    deptName: p?.deptName ?? p?.departmentName ?? '',
    wardName: p?.wardName ?? p?.ward?.name ?? '',
    admissionAt: new Date(),
    deposit: DEFAULT_DEPOSIT_AMOUNT
  }
  admissionDialogVisible.value = true
}
const handleAdmissionSubmit = async payload => {
  try {
    const admission = { ...hospitalInfo.value, admissionTime: payload.admissionAt, deposit: payload.deposit }
    const res = await handleAdmission(admission)
    if (res?.code === 200) {
      await getPatientInfo(patientSelect.value)
      await loadAdmissionList()
      if (payload.deposit > 0) {
        depositInitAmount.value = Number(payload.deposit) || DEFAULT_DEPOSIT_AMOUNT
        const adm = hospitalInfo.value || {}
        depositAdmission.value = {
          patientId: adm?.patientInfo?.patientId || adm?.patientId || 0,
          hospitalizationNumber: adm?.hospitalizationNumber || ''
        }
        depositDialogVisible.value = true
      }
    }
  } catch (e) {
    console.error(e)
  }
}
const openDepositDialog = () => {
  depositInitAmount.value = DEFAULT_DEPOSIT_AMOUNT
  const adm = hospitalInfo.value || {}
  depositAdmission.value = {
    patientId: adm?.patientInfo?.patientId || adm?.patientId || 0,
    hospitalizationNumber: adm?.hospitalizationNumber || ''
  }
  depositDialogVisible.value = true
}
const handleDepositSubmit = async res => {
  if (res?.code === 200) getLoadPaymentList()
}
const changeTab = name => {
  activeName.value = name
  switch (name) {
    case 'his':
      loadAdmissionList()
      break
    case 'hisPay':
      getLoadPaymentList()
      break
  }
}
const getLoadPaymentList = async () => {
  if (!hospitalizationNumber.value) return
  const res = await loadPaymentList({ hospitalizationNumber: hospitalizationNumber.value })
  if (res.code === 200) payList.value = res.data || []
}

// 监听器
watch(
  () => patientSelect.value,
  async newVal => {
    if (Object.keys(newVal || {}).length > 0) {
      hospitalizationNumber.value = newVal.hospitalizationNumber ?? ''
      getPatientInfo(newVal)
      getLoadPaymentList()
      loadAdmissionList()
    }
  },
  { immediate: true, deep: true }
)

// 生命周期
onMounted(() => {
  document.addEventListener('click', handleDocumentClick)
  loadAdmissionList()
})
onUnmounted(() => {
  document.removeEventListener('click', handleDocumentClick)
})
</script>

<style lang="scss" scoped>
@use '@/assets/styles/variables.module.scss' as *;
.left-panel {
  height: 100%;
  background: #fff;
  display: flex;
  flex-direction: column;
}
.search-add {
  width: 100%;
  display: flex;
  margin: 0 auto;
  justify-content: center;
  align-items: center;
  .el-input {
    --el-input-border-radius: 4px 0 0 4px;
  }
  .el-input__inner {
    --el-input-border-radius: 4px 0 0 4px;
  }
  .el-button {
    border-radius: 0 4px 4px 0;
  }
}
.empty-container {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  text-align: center;
}
.medical-cross-icon {
  margin: 0 auto;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  border: 2px solid var(--el-color-primary);
  background-color: var(--el-color-primary-light-9);
  position: relative;
}
.medical-cross-icon::before,
.medical-cross-icon::after {
  content: '';
  position: absolute;
  background-color: var(--el-color-primary);
  border-radius: 2px;
}
.medical-cross-icon::before {
  width: 40px;
  height: 10px;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.medical-cross-icon::after {
  width: 10px;
  height: 40px;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.empty-hint {
  margin-top: 8px;
  font-size: 13px;
  color: var(--el-text-color-secondary);
}
.todo-date {
  display: flex;
  width: 100%;
  margin: 0 auto;
  justify-content: space-between;
  padding: 0 12px;
  align-items: center;
  border-bottom: 1px solid #e4e7ed;
  .tabs {
    position: relative;
  }

  .date-picker {
    position: relative;

    .date-picker-val {
      border: 0;
      background: transparent;
      color: #606266;
      font-size: 14px;
      padding: 8px 12px;

      &:hover {
        background-color: #f5f7fa;
        color: #409eff;
      }
    }

    .date-picker-panel {
      position: absolute;
      top: 100%;
      right: 0;
      z-index: 1000;
      background: #fff;
      border: 1px solid #e4e7ed;
      border-radius: 4px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      padding: 8px;
      margin-top: 4px;
      min-width: 180px;

      // 确保日期选择器样式正确
      :deep(.el-date-editor) {
        width: 100%;

        .el-input__wrapper {
          box-shadow: none;
          border: 1px solid #dcdfe6;
          border-radius: 4px;
        }

        .el-input__inner {
          text-align: center;
          padding: 8px 12px;
        }
      }

      // 日期面板样式
      :deep(.el-picker-panel) {
        margin-top: 8px;
        border: none;
        box-shadow: none;
      }
    }
  }
}
.patient-list {
  padding: 0 6px;
  flex: 1;
  overflow-y: auto;
  ::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }
  ::-webkit-scrollbar-track {
    background-color: #f5f7fa;
  }
  ::-webkit-scrollbar-thumb {
    background-color: #c0c4cc;
    border-radius: 4px;
  }
  ::-webkit-scrollbar-thumb:hover {
    background-color: #909399;
  }
  .patient-item {
    display: flex;
    align-items: center;
    padding: 6px 12px;
    border-radius: 6px;
    margin-top: 6px;
    .patient-icon {
      font-size: 24px;
      margin-right: 8px;
      border-radius: 6px;
      padding: 4px 8px;
      background-color: #e4e7ed;
      color: #606266;
    }
    .patient-info {
      flex: 1;
    }
    .patient-status {
      padding: 4px 8px;
      border-radius: 4px;
      font-size: 14px;
    }
    &:last-child {
      margin-bottom: 6px;
    }
    &:hover {
      background-color: #409eff;
      color: #fff;
    }
    &.active {
      background-color: #409eff;
      color: #fff;
    }
  }
}
.patient-main {
  display: flex;
  flex-direction: column;
}
.patient-title {
  width: 100%;
  display: flex;
  margin: 0 auto;
  height: $sub-navbar-height;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid $border-color;
  padding: 0 $padding-md;
}
.patient-info {
  font-size: $font-size;
}
.patient-content {
  flex: 1;
  padding: $padding-md;
  overflow-y: auto;
  .patient-item {
    margin-bottom: $margin-md;
    .title {
      height: 36px;
      font-size: $font-size;
      line-height: 36px;
      display: flex;
      align-items: center;
      border: solid $border-color;
      border-width: 1px 1px 0 1px;
      padding: 0 $padding-sm;
      width: 100%;
      .read-card {
        margin-left: auto;
      }
    }
    .sub-title {
      font-size: $font-size-sm;
      font-weight: normal;
      margin-left: $margin-sm;
    }
  }
}
.right-panel {
  height: 100%;
  background: #fff;
  display: flex;
  flex-direction: column;
  padding-left: $padding-md;
}
.title {
  height: $sub-navbar-height;
  line-height: $sub-navbar-height;
  font-size: $font-size;
  border-bottom: 1px solid $border-color;
  text-align: center;
}
.his-content {
  flex: 1;
  overflow: auto;
  padding: $padding-md;
  &-item {
    margin-bottom: $margin-md;
    &:last-child {
      margin-bottom: 0;
    }
  }
}
.his-info {
  &-title {
    font-size: $font-size;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  &-content {
    font-size: $font-size;
    margin-top: $margin-sm;
  }
  &-time {
    font-size: $font-size-sm;
    margin-top: $margin-sm;
    color: $sub-font-color;
  }
}
</style>
